package simtester.server

import java.text.DateFormat;
import java.text.SimpleDateFormat

import grails.test.mixin.*
import org.junit.*

/**
 * See the API for {@link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions
 */
@TestFor(TestRunService)
@Mock([User,TestCase,TestRun,ResultEntry,Iteration,Team])
class TestRunServiceTests {
    static testusername = 'testuser'
    static testcasename = 'tc1'
    static testcasescript = 'some script'
    static testcase
    static DateFormat dateFormat = new SimpleDateFormat('MM/dd/yyyy HH:mm:ss.SSS')
    
    def user
    def team
    
    @Before
    void setUp() {
        user = new User(username: 'testuser', password: 'pass')
        team = new Team(name: 'svt')
        team.addToUsers(user)
        
        testcase = new TestCase(name: testcasename, owner: user, script: 'some script')
        team.addToTestcases(testcase)
        team.save(failOnError: true)
    }

    @Test
    void saveTestResults() {
        def expectedUser = 3
        def expectedIter = 2
        def expectedResponse = 100
        def expectedType = 'PUT'
        def tr = new TestRun(testcase: testcase, status: 'completed')
        assert tr.save()

        def logDates = ['01/21/2012 15:11:23.159',
                        '01/21/2012 15:11:23.164',
                        '01/21/2012 15:11:23.180']
        def results = ''
        results += logDates[0] + " INFO: user:$expectedUser iter:$expectedIter|Title: Google\n"
        results += logDates[1] + " INFO: user:$expectedUser iter:$expectedIter type:$expectedType|http://localhost:8080/server\n"
        results += logDates[2] + " INFO: user:$expectedUser iter:$expectedIter resp:$expectedResponse type:$expectedType|http://localhost:8080/server/testRun/update/4f13d4b144aeea17b056ab88 body:[status:completed] content-type:application/json\n"

        service.saveTestRunResults(tr.id, results)

        def entries = ResultEntry.findAllByTestrun(tr)
        assert entries.size() == 3
        assert entries[0].id == 1
        assert entries[1].id == 2
        assert entries[2].id == 3
        
        entries.each {
            assert it.iteration == expectedIter
            assert it.user      == expectedUser
        }

        assert dateFormat.format(entries[0].timestamp) == logDates[0]
        assert dateFormat.format(entries[1].timestamp) == logDates[1]
        assert dateFormat.format(entries[2].timestamp) == logDates[2]
        
        assert entries[0].level == 'INFO'
        assert entries[1].level == 'INFO'
        assert entries[2].level == 'INFO'

        assert entries[0].entry == 'Title: Google'
        assert entries[1].entry == 'http://localhost:8080/server'
        assert entries[2].entry == 'http://localhost:8080/server/testRun/update/4f13d4b144aeea17b056ab88 body:[status:completed] content-type:application/json'
        
        assert !entries[0].type
        assert entries[1].type == expectedType
        assert entries[2].type == expectedType
        
        assert !entries[0].response
        assert !entries[1].response
        assert entries[2].response == expectedResponse
    }
    
    @Test
    void saveTestResultsWithTestCaseId() {
        def expectedUser = 2
        def expectedIter = 1
        def expectedResponse = 100
        def expectedType = 'PUT'

        def testcaseIds = [12L, 40L]
        
        def expectedUsers = [:]
        expectedUsers[testcaseIds[0]] = 3
        expectedUsers[testcaseIds[1]] = 2
        
        def tr = new TestRun(status: 'completed', usersPerTest: expectedUsers)
        assert tr.save()

        def logDates = ['01/21/2012 15:11:23.159',
                        '01/21/2012 15:11:23.164',
                        '01/21/2012 15:11:23.180']
        def results = ''
        results += logDates[0] + " INFO: tc:" + testcaseIds[0] + " user:$expectedUser iter:$expectedIter|Title: Google\n"
        results += logDates[1] + " INFO: tc:" + testcaseIds[0] + " user:$expectedUser iter:$expectedIter type:$expectedType|http://localhost:8080/server\n"
        results += logDates[2] + " INFO: tc:" + testcaseIds[1] + " user:$expectedUser iter:$expectedIter resp:$expectedResponse type:$expectedType|http://localhost:8080/server/testRun/update/4f13d4b144aeea17b056ab88 body:[status:completed] content-type:application/json\n"

        service.saveTestRunResults(tr.id, results)

        def entries = ResultEntry.findAllByTestrun(tr)
        assert entries.size() == 3
        assert entries[0].id == 1
        assert entries[1].id == 2
        assert entries[2].id == 3
        
        entries.each {
            assert it.iteration == expectedIter
            assert it.user      == expectedUser
        }

        assert dateFormat.format(entries[0].timestamp) == logDates[0]
        assert dateFormat.format(entries[1].timestamp) == logDates[1]
        assert dateFormat.format(entries[2].timestamp) == logDates[2]
        
        assert entries[0].level == 'INFO'
        assert entries[1].level == 'INFO'
        assert entries[2].level == 'INFO'
        
        assert entries[0].testcase == testcaseIds[0]
        assert entries[1].testcase == testcaseIds[0]
        assert entries[2].testcase == testcaseIds[1]

        assert entries[0].entry == 'Title: Google'
        assert entries[1].entry == 'http://localhost:8080/server'
        assert entries[2].entry == 'http://localhost:8080/server/testRun/update/4f13d4b144aeea17b056ab88 body:[status:completed] content-type:application/json'
        
        assert !entries[0].type
        assert entries[1].type == expectedType
        assert entries[2].type == expectedType
        
        assert !entries[0].response
        assert !entries[1].response
        assert entries[2].response == expectedResponse
    }
    
    @Test
    void startIteration() {
        def tr = new TestRun(testcase: testcase, status: 'completed')
        tr.save()
        
        def user = 3
        def num = 2
        def results = "03/11/2012 01:53:12.106 INFO: ----- Start Test Run $user:$num -----\n"

        service.saveTestRunResults(tr.id, results)

        def iterations = TestRun.list()[0].iterations
        assert iterations.size() == 1
        assert iterations[0].user   == user
        assert iterations[0].num    == num
        assert iterations[0].status == 'running'
        assert iterations[0].startDate
        assert !iterations[0].endDate
    }
    
    @Test
    void startIterationWithTestCaseId() {
        def testcaseId = 432L
        
        def tr = new TestRun(status: 'completed')
        tr.save()
        
        def user = 3
        def num = 2
        def results = "03/11/2012 01:53:12.106 INFO: ----- Start Test Run $user:$num:$testcaseId -----\n"

        service.saveTestRunResults(tr.id, results)

        def iterations = TestRun.list()[0].iterations
        assert iterations.size() == 1
        assert iterations[0].testcase == testcaseId
        assert iterations[0].user     == user
        assert iterations[0].num      == num
        assert iterations[0].status   == 'running'
        assert iterations[0].startDate
        assert !iterations[0].endDate
    }
    
    @Test
    void endIterationWithSuccess() {
        def user = 2
        def num = 1
        def tr = new TestRun(testcase: testcase, status: 'completed')
        tr.addToIterations(new Iteration(user: user, num: num, startDate: new SimpleDateFormat('MM/dd/yyyy HH:mm:ss.SSS').parse('03/11/2012 01:53:12.106')))
        tr.save(failOnError: true)

        def results = "03/11/2012 01:53:20.087 INFO: user:$user iter:$num|SYS:testrun status:success\n"
        results    += "03/11/2012 01:53:20.090 INFO: ----- End Test Run $user:$num -----\n"

        service.saveTestRunResults(tr.id, results)
        
        def iter = TestRun.list()[0].iterations[0]
        assert iter.status == 'success'
        assert iter.endDate
        assert iter.duration().toString() == '7.984 seconds'
    }
    
    @Test
    void endIterationWithTestCaseIdWithSuccess() {
        def tc = 32L
        def user = 2
        def num = 1
        def tr = new TestRun(status: 'completed')
        tr.addToIterations(new Iteration(testcase: tc, user: user, num: num, startDate: new SimpleDateFormat('MM/dd/yyyy HH:mm:ss.SSS').parse('03/11/2012 01:53:12.106')))
        tr.save(flush: true, failOnError: true)

        def results = "03/11/2012 01:53:20.087 INFO: tc:$tc user:$user iter:$num|SYS:testrun status:success\n"
        results    += "03/11/2012 01:53:20.090 INFO: ----- End Test Run $user:$num:$tc -----\n"

        service.saveTestRunResults(tr.id, results)
        
        def iter = TestRun.list()[0].iterations[0]
        assert iter.testcase == tc
        assert iter.status == 'success'
        assert iter.endDate
        assert iter.duration().toString() == '7.984 seconds'
    }
    
    @Test
    void endIterationWithFailure() {
        def user = 3
        def num = 1
        def tr = new TestRun(testcase: testcase, status: 'completed')
        tr.addToIterations(new Iteration(user: user, num: num, startDate: new SimpleDateFormat('MM/dd/yyyy HH:mm:ss.SSS').parse('03/11/2012 01:53:12.106')))
        tr.save()

        def results = "03/11/2012 01:53:20.087 INFO: user:$user iter:$num|SYS:testrun status:failed\n"
        results    += "03/11/2012 01:53:20.090 INFO: ----- End Test Run $user:$num -----\n"

        service.saveTestRunResults(tr.id, results)
        
        def iter = TestRun.list()[0].iterations[0]
        assert iter.status == 'failed'
        assert iter.endDate
        assert iter.duration().toString() == '7.984 seconds'
    }

}
